package com.sikaryofficial.backend.controller;

import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson2.JSONObject;
import com.sikaryofficial.backend.domain.dto.req.UserSettingEmailReq;
import com.sikaryofficial.backend.domain.mapping.SysUserMapping;
import com.sikaryofficial.backend.service.IPointsDetailStrategy;
import com.sikaryofficial.backend.service.IUserCertificateService;
import com.sikaryofficial.backend.service.points.cache.PointsRuleConfigCacheService;
import com.sikaryofficial.common.core.constant.PointRuleConstant;
import com.sikaryofficial.common.core.domain.R;
import com.sikaryofficial.common.core.exception.ServiceException;
import com.sikaryofficial.common.core.utils.HiResultUtil;
import com.sikaryofficial.common.core.web.controller.BaseController;
import com.sikaryofficial.common.core.web.domain.AjaxResult;
import com.sikaryofficial.common.core.web.domain.HiResult;
import com.sikaryofficial.common.redis.service.RedisService;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import com.sikaryofficial.system.api.RemoteProfileService;
import com.sikaryofficial.system.api.RemoteUserService;
import com.sikaryofficial.system.api.domain.SysUser;
import com.sikaryofficial.system.api.model.SysUserEmailReq;
import com.sikaryofficial.system.api.model.SysUserNickNameReq;
import com.sikaryofficial.system.api.model.SysUserReq;
import com.sikaryofficial.system.api.model.UserPointResultVO;
import com.sikaryofficial.system.api.model.UserProfileReq;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * H5页面需要新增的接口
 *
 * @author qinjinyuan
 * @date 2023-10-27
 */
@RestController
@RequestMapping("/user/setting")
@Api(tags = "用户设置")
@Slf4j
public class UserSettingController extends BaseController {

    @Autowired
    private RemoteProfileService remoteProfileService;

    @Autowired
    private IUserCertificateService userCertificateService;
    @Resource
    private RemoteUserService remoteUserService;
    @Resource
    private Map<String, IPointsDetailStrategy> pointsDetailStrategyMap;
    @Autowired
    private RedisService redisService;
    @Resource
    private PointsRuleConfigCacheService ruleConfigCacheService;

    @ApiOperation("判定是否有满18岁证明")
    @PostMapping("/valid18thProof")
    public HiResult valid18thProof() {
        Long userId = SecurityUtils.getUserId();
        if (Objects.isNull(userId) || userId <= 0) {
            throw new ServiceException("param error.");
        }
        return HiResultUtil.success(userCertificateService.validate18thProof(userId));
    }

    @ApiOperation("获取满18岁证明")
    @GetMapping("/get18thProof")
    public HiResult<String> get18thProof() {
        Long userId = SecurityUtils.getUserId();
        if (Objects.isNull(userId) || userId <= 0) {
            throw new ServiceException("param error.");
        }
        return HiResultUtil.success(userCertificateService.get18thProof(userId));
    }

    @ApiOperation("更新个人中心背景")
    @PostMapping("/updateBackImg")
    public AjaxResult updateBackImg(@RequestPart(value = "file") MultipartFile file, @RequestHeader("deviceId") String deviceId, @RequestHeader("channel") String channel) {
        return remoteProfileService.updateBackImg(file, deviceId, channel);
    }

    @ApiOperation("V2.5-修改昵称")
    @PostMapping("/updateNickName")
    public AjaxResult updateNickName(@Validated @RequestBody SysUserNickNameReq req) {
        return remoteProfileService.updateNickName(req);
    }

    @ApiOperation("修改邮箱")
    @PostMapping("/updateEmail")
    public AjaxResult updateEmail(@Validated @RequestBody UserSettingEmailReq req, @RequestHeader("deviceId") String deviceId, @RequestHeader("channel") String channel) {
        SysUserEmailReq sysUserEmailReq = new SysUserEmailReq();
        sysUserEmailReq.setEmail(req.getEmailAddress());
        sysUserEmailReq.setCaptcha(req.getCaptchaCode());
        return remoteProfileService.updateEmail(sysUserEmailReq, deviceId, channel);
    }

    @ApiOperation("编辑个人信息")
    @PutMapping
    public AjaxResult updateProfile(@Validated @RequestBody SysUserReq user, @RequestHeader("deviceId") String deviceId, @RequestHeader("channel") String channel) {
        Long userId = SecurityUtils.getUserId();
        String url = user.getProofUrl();
        if (Objects.isNull(userId) || userId <= 0) {
            throw new ServiceException("param error.");
        }
        // 如果传入18岁证明,则进行证书上传
        if (CharSequenceUtil.isNotBlank(url) && !userCertificateService.update18thProof(url, userId)) {
            throw new ServiceException("update 18th Proof error.");
        }
        // 远程调用，数据更新
        R<SysUser> sysUserResult = remoteUserService.getUserByUserId(userId);
        if (Objects.isNull(sysUserResult) || Objects.isNull(sysUserResult.getData())) {
            throw new ServiceException("update 18th Proof error.");
        }
        log.info("sysUserResult {}", JSONObject.toJSONString(sysUserResult));
        AjaxResult ajaxResult = remoteProfileService.updateProfile(SysUserMapping.INSTANCE.coverToEntity(user), deviceId, channel);
        if (ajaxResult.isError()) {
            throw new ServiceException("Update Error: " + ajaxResult.get("msg") );
        }
        UserPointResultVO data = UserPointResultVO
                .builder()
                .pointsDetailValue(0)
                .getPointsFlag(false)
                .build();
        // 新旧数据对比，如果修改的数据，在变更范围 ： firstName, lastName, age, Gender
        // 1、首次修改完【first ，last name，age，gender】获得积分，仅在同时修改完以上字段才有积分获取
        // sysUserResult.getData()  ,  SysUserReq user
        log.info("ajaxResult {}", JSONObject.toJSONString(ajaxResult));
        if (R.isSuccess(sysUserResult) && Objects.nonNull(sysUserResult.getData())) {
            SysUser sysUser = sysUserResult.getData();
            boolean firstNameFlag = !Objects.equals(sysUser.getFirstName(), user.getFirstName());
            boolean lastNameFlag = !Objects.equals(sysUser.getLastName(), user.getLastName());
            boolean sexFlag = !Objects.equals(sysUser.getSex(), user.getSex());
            boolean birthDateFlag = !Objects.equals(sysUser.getBirthDate(), user.getBirthDate());
            // 记录下redis 比较结果数据
            redisService.setCacheObject("user:setting:update:" + userId, sysUser.toString().concat("; inputValue " + user), 1L, TimeUnit.HOURS);
            if (firstNameFlag && lastNameFlag && sexFlag && birthDateFlag) {
                // 积分处理
                processPoints(userId, data);
            }
        }
        return this.success(data);
    }

    /**
     * 个人信息更新，积分处理
     *
     * @param userId 用户ID
     */
    private void processPoints(Long userId, UserPointResultVO data) {
        IPointsDetailStrategy pointsDetailStrategy = pointsDetailStrategyMap.get(PointRuleConstant.OWNER_INFO_MODIFY + IPointsDetailStrategy.SUFFIX);
        // 评价获取积分
        boolean result = pointsDetailStrategy.updatePoints(userId, userId);
        Integer pointsDetailValue = ruleConfigCacheService.getConfigByCode(PointRuleConstant.OWNER_INFO_MODIFY).getPointsValue();
        if (Boolean.TRUE.equals(result)) {
            data.setPointsDetailValue(pointsDetailValue);
        }
        data.setGetPointsFlag(result);
    }

    @ApiOperation("登录编辑个人信息")
    @PutMapping("/updateUserProfile")
    public AjaxResult updateUserProfile(@Validated @RequestBody UserProfileReq user, @RequestHeader("deviceId") String deviceId, @RequestHeader("channel") String channel) {
        Long userId = SecurityUtils.getUserId();
        if (Objects.isNull(userId) || userId <= 0) {
            throw new ServiceException("param error.");
        }
        return remoteProfileService.updateProfile(SysUserMapping.INSTANCE.coverReqToEntity(user), deviceId, channel);
    }

    @ApiOperation("更新个人图像")
    @PostMapping("/avatar")
    public AjaxResult avatar(@RequestPart(value = "avatarfile") MultipartFile file, @RequestHeader("deviceId") String deviceId, @RequestHeader("channel") String channel) {
        return remoteProfileService.updateAvatar(file, deviceId, channel);
    }
}
